#include <arpa/inet.h>
#include <iostream>
#include <netinet/in.h>
#include <sys/epoll.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{
    //创建epoll的文件描述符
    int epfd = epoll_create(10000);
    int server_sock = socket(AF_INET, SOCK_STREAM, 0);
    if (server_sock == -1) {
	std::cerr << "Socket Error" << std::endl;
	return 1;
    }

    sockaddr_in serveraddr;
    unsigned short serverport = 6666;
    serveraddr.sin_family = AF_INET;
    serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);
    serveraddr.sin_port = htons(serverport);

    if (bind(server_sock, reinterpret_cast<sockaddr*>(&serveraddr), sizeof(serveraddr)) == -1) {
	std::cerr << "Socket bind error" << std::endl;
	close(server_sock);
	return -1;
    }
    if (listen(server_sock, 10) != 0) {
	std::cerr << "Socket listen error" << std::endl;
	close(server_sock);
	return -1;
    }

    //此时，应该等待网络连接了,将其加入到epoll的监听队列之中。
    epoll_event server_event;
    server_event.events = EPOLLIN;
    server_event.data.fd = server_sock;
    epoll_ctl(epfd, EPOLL_CTL_ADD, server_sock, &server_event);

    epoll_event wait_event[1000];

    sockaddr_in client_address;
    socklen_t client_len;

    while (true) {
	int wait_todo = epoll_wait(epfd, wait_event, 1000, -1);
	for (int i = 0; i < wait_todo; ++i) {
	    //此时服务端的serversock可读，说明来了新链接，需要加入到监听库之中。
	    if ((wait_event[i].events & EPOLLIN) && (wait_event[i].data.fd == server_sock)) {
		int client_sock = accept(server_sock, reinterpret_cast<sockaddr*>(&client_address), &client_len);
		epoll_event client_event;
		client_event.events = EPOLLIN | EPOLLRDHUP;
		client_event.data.fd = client_sock;
		epoll_ctl(epfd, EPOLL_CTL_ADD, client_sock, &client_event);
	    } else if ((wait_event[i].events & EPOLLIN) && (!(wait_event[i].events & EPOLLRDHUP))) {
		std::cout << "Data input" << std::endl;
		write(wait_event[i].data.fd, "s", 2);
	    } else if ((wait_event[i].events & EPOLLIN) && ((wait_event[i].events & EPOLLRDHUP))) {
		//此时说明有的描述符需要关闭,直接关闭网络链接。
		epoll_ctl(epfd, EPOLL_CTL_DEL, wait_event[i].data.fd, NULL);
		close(wait_event[i].data.fd);
	    } else {
		epoll_ctl(epfd, EPOLL_CTL_DEL, wait_event[i].data.fd, NULL);
		close(wait_event[i].data.fd);
	    }
	}
    }

    return 0;
}
